package de.fuberlin.inf.alp2;

import java.util.Iterator;
import java.util.LinkedList;

public class ListPolygon implements Polygon {

	LinkedList<Point> points;
	Rectangle plane;
	
	public ListPolygon(){
		this.plane = new Rectangle(new Point(100,100));
		points = new LinkedList<Point>();
	}
	
	@Override
	public boolean addPoint(Point p) throws Exception {
		if ((p.getX() > this.plane.getUpperRight().getX()) ||
				(p.getY() > this.plane.getUpperRight().getY()))
			throw new Exception("Point could not be added - Polygon would " +
					"reach out of plane");
		this.points.add(p);
		return true;
	}

	@Override
	public Point center() throws Exception {
		if (!isPolygon())
			throw new Exception("The centroid could not be calculated, cause" +
					" the points do not form a polygon");
		int sumOfX = 0, sumOfY = 0;
		int size = points.size();
		for (Point point : points) {
			sumOfX += point.getX();
			sumOfY += point.getY();
		}
		return new Point((sumOfX / size), (sumOfY / size));
	}

	@Override
	public double perimeter() throws Exception {
		if (!isPolygon())
			throw new Exception("The perimeter could not be calculated, cause" +
					" the points do not form a polygon");
		Iterator<Point> i = points.iterator();
		double ret = 0.0;
		Point preCurrent = points.getLast();
		while (i.hasNext()){
			Point current = i.next();
			ret += current.distance(preCurrent);
			preCurrent = current;
		}
		return ret;
	}

	@Override
	public void shift(int dx, int dy) throws Exception {
		LinkedList<Point> shiftedPoints = new LinkedList<Point>();
		for (Point point : this.points) {
			Point shiftedPoint = new Point(point);
			shiftedPoint.translate(dx, dy);
			if ((shiftedPoint.getX() > this.plane.getUpperRight().getX()) ||
					(shiftedPoint.getY() > this.plane.getUpperRight().getY()))
				throw new Exception("Shift not allowed - Polygon would reach " +
						"out of plane");
			shiftedPoints.add(shiftedPoint);
		}
		this.points = shiftedPoints;
	}

	@Override
	public boolean isPolygon() {
		int size = points.size();
		if (size > 2)
		{
			Point start = points.get(0);
			double gradient = Point.getGradient(start, points.get(1));
			for (int i = 2; i < size; i++)
				if (gradient != Point.getGradient(start, points.get(i)))
					return true;
		}
		return false;
	}

	public java.util.List<Point> getPoints() {
		return points;
	}
}
